<?php

namespace app\common\library;

use app\admin\model\Setting;
use app\admin\model\Transaction;
use app\admin\model\user\Balance;
use app\admin\model\user\Extend;
use app\admin\model\Store;
use app\admin\model\Room;
use app\common\library\Tongtongsuo;
use app\common\library\Yunding;
use app\common\library\Pay as PayLib;
use app\common\model\Third;
use addons\qcloudsms\Qcloudsms;
use Carbon\Carbon;
use EasyWeChat\Factory;
use fast\Http;
use tests\thinkphp\library\think\behavior\Three;
use think\Db;
use think\Env;
use think\Log;

class Reserve
{
    protected $_declineCredit = 0;
    protected $_refundMoney = 0;
    protected $_rentCancel = 0;
    protected $_rentRefund = 0;

    protected $perSeconds = 60 * 30;
    protected $perHour = 60 * 60;
    protected $_calcStartTime = 0;

    public function __construct($declineCredit = 0, $refundMoney = 0, $rentCancel = 0, $rentRefund = 0)
    {
        if ($declineCredit) {
            $this->_declineCredit = $declineCredit;
        }
        if ($refundMoney) {
            $this->_refundMoney = $refundMoney;
        }
        if ($rentCancel) {
            $this->_rentCancel= $rentCancel;
        }
        if ($rentRefund) {
            $this->_rentRefund = $rentRefund;
        }
        $this->_calcStartTime = Env::get('common.calc_starttime');
    }


    public function calcCancelReserve($userId, $reserve = null, $id = 0)
    {
        $ret = [
            'code'  => 0,
            'msg' => '',
            'data' => [
                'user_credit' => 0,
                'decline_credit' => 0,
                'pay_money' => 0,
                'pass_reserve_info' => [],
            ],
        ];
        $msg = '';
        if ($reserve === null && $id) {
            $reserve = \app\admin\model\Reserve::get($id, ['room', 'store']);
        }
        if (!$reserve) {
            $ret['code'] = -1;
            $ret['msg'] = '无预约记录';
        }
        if ($ret['code'] < 0) {
            return $ret;
        }
        // 查找预约信息
        $reserveInfo = [];
        $reserveInfo['store'] = $reserve->store['store_name'];
        $reserveInfo['room'] = $reserve->room['room_name'];
        $reserveInfo['order_time'] = date('m/d H:i', strtotime($reserve->starttime)) . '至' . date('H:i', strtotime($reserve->endtime));
        // 如果有卡券支付
        $payInfo = '';
        $payLib = new PayLib($userId, $reserve->id);
        $consumeHour = 0;
        $balance = 0;
        if ($reserve->card_id) {
            $consumeHour = $payLib->cardData($reserve);
            $payInfo = '卡券支付' . $consumeHour . '小时';
        }
        if ($reserve->balance_id) {
            $balance = $payLib->balanceData($reserve);
            $payInfo = '余额支付' . $balance. '元';
        }
        if ($reserve->transaction_id) {
            $wechat = $payLib->wechatData($reserve);
            if ($consumeHour != 0 || $balance != 0) {
                $payInfo .= '+';
            }
            $payInfo .= '微信支付' . $wechat . '元';
        }
        $reserveInfo['pay_info'] = $payInfo;
        $ret['data']['reserve_info'] = $reserveInfo;

        $userExtend = Extend::where('user_id', $userId)->find();
        $userCredit = $userExtend->credit_score;
        $ret['data']['user_credit'] = $userCredit;
        $createTime = date('Y-m-d H:i:s', $reserve->createtime);
        // 计算是否超过无责取消时间
        if (Carbon::parse($createTime)->addMinutes($this->_rentCancel)->isAfter(Carbon::now())) {
            $ret['data']['pay_money'] = 0;
            $ret['data']['decline_credit'] = 0;
            $ret['data']['tip'] = '本次预约在下单后的'.$this->_rentCancel.'分钟内取消，无需扣除信用分';
        } else {
            // 计算
            $starttime = strtotime($reserve->starttime); 
            $endtime = strtotime($reserve->endtime);
            // 订单创建时间大于更新时间
            if ($reserve->createtime > $this->_calcStartTime) {
                $endtime += 60;
            }

            $diffTime = $endtime - $starttime;
            $diffHour = $diffTime / $this->perHour;
            $diffUnit = $diffTime / $this->perSeconds;
            $declineScore = $diffUnit * $this->_declineCredit;

            $diffScore = $userCredit - $declineScore;
            if ($diffScore >= 0) {
                $ret['data']['pay_money'] = 0;
                $ret['data']['decline_credit'] = $declineScore;
                $ret['data']['tip'] = '您的预约时间为'.$diffHour.'小时，取消须扣除'.$declineScore.'个信用分，扣除后您的信用分为' . ($userCredit - $declineScore);
            } else {
                $ret['data']['pay_money'] = abs($diffScore * $this->_refundMoney);
                $ret['data']['decline_credit'] = $userCredit;
                $ret['data']['tip'] = '您的预约时间为'.$diffHour.'小时，取消须扣除'.$declineScore.'个信用分，你当前信用分为'.$userCredit.'分，不足部分须微信支付';
                $ret['data']['pay_tip'] = '差'.abs($diffScore).'个信用分，1个信用分='.$this->_refundMoney.'元';
                $ret['data']['pass_reserve_info'] = [
                    'decline_credit' => $userCredit,
                    'price' => abs($diffScore * $this->_refundMoney),
                    'reserve_id' => $reserve->id,
                ];
            }
        }

        return $ret;
    }
    
    // 取消预约
    public function cancelReserve($userId, $reserve = null, $id = 0)
    {
        $ret = [
            'code'  => 0,
            'msg' => '',
        ];
        $msg = '';
        if ($reserve === null && $id) {
            $reserve = \app\admin\model\Reserve::get($id, ['room']);
        }
        if (!$reserve) {
            $ret['code'] = -1;
            $ret['msg'] = '无预约记录';
        }
        if ($ret['code'] < 0) {
            return $ret;
        }
        Db::startTrans();

        try {
            $payLib = new PayLib($userId, $reserve->id);
            // 卡券的取消
            if (!empty($reserve->card_id)) {
                $payLib->cardRefund($reserve);
            }
            // 余额支付
            if (!empty($reserve->balance_id)) {
                $payLib->balanceRefund($reserve);
            }
            // 有微信支付
            if (!empty($reserve->transaction_id)) {
                $payLib->wechatRefund($reserve);
            }
            //如果有优惠券，恢复
            $payLib->couponRefund($reserve->user_coupon_id);

            // 标记Reserve是取消了
            $reserve->re_status = 2;
            $reserve->save();

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $ret['code'] = -1;
            $ret['msg'] = $e->getMessage();
        }
        
        return $ret; 
    }

    // 更新预约表
    /*
     payData 参数形式
     payData = [
        ['pay_way' => 1, 'field_name' => 'card_id', 'field_val' => 1] 
     ]
     or 
     payData = ['pay_way' => 1, 'field_name' => 'card_id', 'field_val' => 1] 
    */
    public function updateReserve($reserve, $payData, $tts, $couponid = null, $fee = 0)
    {
        $reserve->re_status = 1;
        // 只一种支付
        if (array_key_exists('pay_way', $payData)){
            $fieldName = $payData['field_name'];
            $reserve->pay_way = $payData['pay_way'];
            $reserve->$fieldName = $payData['field_val'];
        } else if (array_key_exists(0, $payData) && count($payData) > 1) {
            // 组合支付
            $reserve->pay_way = 5;
            foreach ($payData as $pd) {
              if (isset($pd['field_name'])) {
                  $fieldName = $pd['field_name'];
                  $reserve->$fieldName = $pd['field_val'];
              }
            }
        }
        if (!empty($fee)) {
            $reserve->fee = $fee;
        }
        $reserve->user_coupon_id = $couponid;
        $reserve->tts_bluekeyid = $tts['blue_key_id'] ?? '';
        $reserve->tts_bluelockdata = $tts['blue_lock_data'] ?? '';
        $reserve->tts_randkeyid = $tts['rand_key_id'] ?? '';
        $reserve->tts_randkeypwd = $tts['rand_key_pwd'] ?? '';
        $reserve->save();
        // 发送短信
        $this->smsNotice($reserve);
    
    }
    
    // 选择卡支付时
    public function cardPay($reserve, $cardId, $timepills)
    {
        $ret = [
            'pay_money' => 0,
            'card_id' => 0,
            'card_name' => '',
            'discout_duration' => 0,
            'pass_reserve_info' => [],
        ];
        $cardInfo = $this->checkCard($reserve, $cardId); 
        if (empty($cardInfo)) {
            $ret['pay_money'] = $reserve->fee;
            $passReserveInfo = [
                'reserve_id' => $reserve->id,
                'room_id' => $reserve->room_id,
                'selectdate' => date('Y-m-d', strtotime($reserve->starttime)),
                'start' => $reserve->starttime,
                'end' => $reserve->endtime,
                'price' => $reserve->fee,
                'card_id' => 0,
                'consume_hour' => 0,
            ];
            $ret['pass_reserve_info'] = $passReserveInfo;
            return $ret;
        }
        $diffDuration = $cardInfo['diff_duration'];
        $ret['card_id'] = $cardId;
        $ret['card_name'] = $cardInfo['name'];
        // 卡不足够支付
        if ($diffDuration < 0) {
            $matchPills = $this->matchMinTime($timepills, abs($diffDuration));
            $payMoney = 0;
            foreach ($matchPills as $pill) {
                $payMoney += $pill['price'];
            }
            $ret['pay_money'] = $payMoney;
            $ret['discout_duration'] = $cardInfo['card_duration'];
            $passReserveInfo = [
                'reserve_id' => $reserve->id,
                'room_id' => $reserve->room_id,
                'selectdate' => date('Y-m-d', strtotime($reserve->starttime)),
                'start' => $reserve->starttime,
                'end' => $reserve->endtime,
                'price' => $payMoney,
                'card_id' => $cardId,
                'consume_hour' => $cardInfo['card_duration'] / 60,
            ];
            $ret['pass_reserve_info'] = $passReserveInfo;
        } else {
            $ret['discout_duration'] = $cardInfo['total_duration'];
        }
        
        return $ret;    
    }
    
    // 选择余额支付
    public function balancePay($reserve, $userId, $userExtend)
    {
        $ret = [
            'pay_money' => 0,
            'balance' => 0,
            'pass_reserve_info' => [],
        ];
        $reserveUserId = $reserve->user_id;
        if ($userId != $reserveUserId) {
            return $ret;
        }
        $balance = $userExtend->balance;
        $balancePay = $reserve->fee;
        $payMoney = $balance - $reserve->fee;
        if ($payMoney >= 0)  {
            $payMoney = 0;
        } else {
            $payMoney = abs($payMoney);
            $balancePay = $balance;
            $passReserveInfo = [
                'reserve_id' => $reserve->id,
                'room_id' => $reserve->room_id,
                'selectdate' => date('Y-m-d', strtotime($reserve->starttime)),
                'start' => $reserve->starttime,
                'end' => $reserve->endtime,
                'price' => $payMoney,
                'balance' => $balancePay,
            ];
            $ret['pass_reserve_info'] = $passReserveInfo;
        }

        $ret['pay_money'] = $payMoney;
        $ret['balance'] = $balancePay;

        return $ret;
    }
    
    // 选择微信支付
    public function wechatPay($reserve, $userId, $couponid = null)
    {
        $ret = [
            'pay_money' => 0,
            'couponid' => 0,
            'coupon_name' => '',
            'discout_price' => 0,
            'pass_reserve_info' => [],
        ];
        $couponInfo  = $this->checkCoupon($reserve, $userId, $couponid);
        $passReserveInfo = [
            'reserve_id' => $reserve->id,
            'room_id' => $reserve->room_id,
            'selectdate' => date('Y-m-d', strtotime($reserve->starttime)),
            'start' => $reserve->starttime,
            'end' => $reserve->endtime,
        ];
        if (empty($couponInfo)) {
            $ret['pay_money'] = $reserve->fee;
            $passReserveInfo['price'] = $reserve->fee;
            $passReserveInfo['couponid'] = 0;
            $ret['pass_reserve_info'] = $passReserveInfo;
            return $ret;
        }

        $payMoney = $reserve->fee - $couponInfo['price'];
        // 优惠券完全抵扣
        if ($payMoney <= 0) {
            $payMoney = 0;
        }  
        $ret['pay_money'] = $payMoney;
        $ret['couponid'] = $couponInfo['id'];
        $ret['coupon_name'] = $couponInfo['name'];
        $ret['discout_price'] = $couponInfo['price'];
        $passReserveInfo['price'] = $payMoney;
        $passReserveInfo['couponid'] = $couponInfo['id'];
        $ret['pass_reserve_info'] = $passReserveInfo;

        return $ret;
    }
    
    // 匹配价格最少的时段
    public function matchMinTime($timepills, $diffDuration)
    {
        foreach ($timepills as &$pill) {
            $pill['price'] = intval($pill['price']);
            $pill['duration'] = intval($pill['duration']);
        }
        unset($pill);
        // 按价格排序
        array_multisort(array_column($timepills, 'price'), SORT_ASC, $timepills);
        $newpills = [];
        $plusDuration = 0;
        foreach ($timepills as $pill) {
            if ($plusDuration >= $diffDuration) {
                break;
            }
            $newpills[] = $pill;
            $plusDuration += $pill['duration'];
        }

        return $newpills;
    }
    // 判断选择的卡是否有效可用
    public function checkCard($reserve, $cardId)
    {
        $cardInfo = [];
        if (!empty($reserve)) {
            $userId = $reserve->user_id; 
            $startTime = Carbon::parse($reserve->starttime);
            $endTime = Carbon::parse($reserve->endtime);
            if ($endTime->minute == 29 || $endTime->minute == 59) {
                $endTime->addMinute();
            }
            $selectDate = $startTime->toDateString();
            $reserveDuration = $startTime->diffInMinutes($endTime, false);
            $roomId = $reserve->room_id;

            $supportCards = \app\common\model\Card::getCouldUseCardList($userId, $selectDate, $reserveDuration, $roomId);
            foreach ($supportCards as $card) {
                if ($cardId == $card['id']) {
                    $cardInfo = $card->toArray();
                    // 计算相差的分钟数
                    $cardDuration = ($card['total_hour'] - $card['hasconsumedhour']) * 60;
                    $cardInfo['total_duration'] = $reserveDuration;
                    $cardInfo['card_duration'] = $cardDuration;
                    $cardInfo['diff_duration'] = ($cardDuration - $reserveDuration);
                }
            }
        }

        return $cardInfo;
    }

    public function checkCoupon($reserve, $userId, $couponId = null)
    {
        $couponInfo = [];
        $coupons = \app\admin\model\user\Coupon::where('user_id', $userId)
            ->where('is_used', 0)
            ->where('start_time', '<=', Carbon::now()->toDateString())
            ->where('end_time', '>=', Carbon::now()->toDateString())
            ->where('min_price', '<=', $reserve->fee)
            ->order('reduce_price desc')
            ->select();
        $data = array_map(function ($e) {
            return [
                'id' => $e->id,
                'name' => $e->coupon_name,
                'price' => $e->reduce_price,
                'min_price' => $e->min_price,
                'starttime' => $e->start_time,
                'endtime' => $e->end_time,
            ];
        }, $coupons);
        // 如果没有优惠券参数，给找个折扣最大的
        if (empty($couponId) && !empty($data)) {
            $couponInfo = $data[0];
        } else {
            // 如果有选择需要判断是否合理
            foreach ($data as $d) {
                if ($d['id'] == $couponId) {
                    $couponInfo = $d;
                }
            }
        }
        
        return $couponInfo; 
    }

    public function getRoomPills($room, $passDate, $checkIsOpen = 0)
    {
        $dateParse = Carbon::parse($passDate);

        $rentPills = empty($room->rent_time) ? [] : json_decode($room->rent_time, true);
        $weekRentPills = empty($room->week_rent_time) ? [] : json_decode($room->week_rent_time, true);
        $dayOfWeek = 'week' . $dateParse->dayOfWeek;
        if ($dayOfWeek == 'week0') {
            $dayOfWeek = 'week7';
        }
        if (!empty($weekRentPills[$dayOfWeek])) {
            $rentPills = $weekRentPills[$dayOfWeek];
        }

        $dateRentPills = empty($room->date_rent_time) ? [] : json_decode($room->date_rent_time, true);
        $dateSetting = empty($room->date_setting) ? [] : json_decode($room->date_setting, true);
        if (!empty($dateSetting)) {
            $open = $dateSetting['open'];
            if ($passDate >= $dateSetting['date1'] && $passDate <= $dateSetting['date2']) {
                if ($open === '0') {
                    $rentPills = [];
                } else {
                    $rentPills = $dateRentPills;
                }
            }
        }
        // 查找房间标记是已占用的pill
        if ($checkIsOpen) {
            $newPills = [];
            foreach ($rentPills as $pill) {
                if (isset($pill['is_open']) && $pill['is_open'] === '0' ) {
                    $newPills[] = $pill;
                }
            }
            $rentPills = $newPills;
        }

        return $rentPills;
    }

    public function smsNotice($reserve)
    {
        $store = Store::where('id', $reserve->store_id)->find();
        if (!$store || strlen($store->mobiles) < 11) {
            Log::write("未配置手机号, reserve id =>" . $reserve->id);
            return;
        }
        $mobiles = str_replace("，", ",", $store->mobiles);
        $room = Room::where('id', $reserve->room_id)->find();
        if (!$room) {
            Log::write("未找到教室, reserve id =>" . $reserve->id);
            return;
        }
        $roomName = mb_substr($room->room_name, 0, 5);
        // 查找用户实名的姓名
        $userExtend = Extend::where('user_id', $reserve->user_id)->find();
        if (!$userExtend) {
            Log::write("未找到用户扩展信息, reserve id =>" . $reserve->id);
            return;
        }
        $username = $userExtend->name;
        if (mb_strlen($username) == 2) {
            $username = mb_substr($username, 0, 1) . "*";
        } else {
            $username = mb_substr($username, 0, 1) . "*" . mb_substr($username, -1, 1);
        }
        $ordertime = date('H:i', $reserve->createtime);
        $orderdate = date('n月j', $reserve->createtime);
        $startdate = date('n月j', strtotime($reserve->starttime));
        $starttime = date('H:i', strtotime($reserve->starttime));
        $diffHour = (strtotime($reserve->endtime) - strtotime($reserve->starttime) + 60) / 3600;
        $diffHour = number_format($diffHour, 1, '.', '');
        $qcloudsms = new Qcloudsms();
        $mobiles = explode(",", $mobiles);
        // $roomName = '测试教室';
        foreach ($mobiles as $m) {
            $params = [
                'mobile'  => $m,
                'template' => '2144950',
                'msg' => [
                    'orderdate' => $orderdate,
                    'ordertime' => $ordertime,
                    'roomname' => $roomName,
                    'startdate' => $startdate,
                    'starttime' => $starttime,
                    'diffHour' => $diffHour,
                ],
            ];
            Log::write("发送内容, =>" . var_export($params, true));
            $check = $qcloudsms->smsNotice($params);
            if ($check) {
              Log::write("发送成功, reserve id =>" . $reserve->id);
            } else {
              $err = $qcloudsms->getError();
              Log::write("发送失败，错误代码:" . $err['result'] . ", 错误描述:" . $err['errmsg']);
            }
        }
    
    }

}
